home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 001a / mskrmsrc.zip / MSNBTP.C < prev    next >
C/C++ Source or Header  |  1991-10-24  |  9KB  |  268 lines

  1. /* File MSNBTP.C
  2.  * Bootp requestor
  3.  *
  4.  * Copyright (C) 1991, University of Waterloo.
  5.  * Copyright (C) 1991, Trustees of Columbia University in the
  6.  *  City of New York.  Permission is granted to any individual or
  7.  *  institution to use, copy, or redistribute this software as long as
  8.  *  it is not sold for profit and this copyright notice is retained.
  9.  *
  10.  * Original version created by Erick Engelke of the University of
  11.  *  Waterloo, Waterloo, Ontario, Canada.
  12.  * Adapted and modified for MS-DOS Kermit by Joe R. Doupnik, 
  13.  *  Utah State University, jrd@cc.usu.edu, jrd@usu.Bitnet.
  14.  *
  15.  * Last edit
  16.  * 6 Sept 1991
  17.  *
  18.  *   BOOTP - Boot Protocol (RFC 854)
  19.  *
  20.  *   These extensions get called if bootphost is set to an IP address or
  21.  *   to 0xffffffff.
  22.  *
  23.  */
  24.  
  25. #include "msntcp.h"
  26. #include "msnlib.h"
  27.  
  28. /*
  29.  * Bootstrap Protocol (BOOTP)
  30.  * Based on RFC 951.
  31.  */
  32.  
  33. #define BOOTREQUEST     1    /* bootp.bp_op */
  34. #define BOOTREPLY    2
  35.  
  36. /*
  37.  * structure for send and receives
  38.  */
  39. typedef struct bootp {
  40.     byte     bp_op;        /* packet op code / message type. */
  41.     byte     bp_htype;    /* hardware address type, 1 = 10 mb ethernet */
  42.     byte     bp_hlen;    /* hardware address len, eg '6' for 10mb eth */
  43.     byte     bp_hops;    /* client sets to zero, optionally used by
  44.                    gateways in cross-gateway booting. */
  45.     longword bp_xid;    /* transaction ID, a random number */
  46.     word     bp_secs;    /* filled in by client, seconds elapsed since
  47.                    client started trying to boot. */
  48.     word     bp_spare;
  49.     longword bp_ciaddr;    /* client IP address filled in by client */
  50.                 /*  if known*/
  51.     longword bp_yiaddr;    /* 'your' (client) IP address
  52.                    filled by server if client doesn't know */
  53.     longword bp_siaddr;    /* server IP address returned in bootreply */
  54.     longword bp_giaddr;    /* gateway IP address,
  55.                    used in optional cross-gateway booting. */
  56.     byte     bp_chaddr[16];    /* client hardware address, filled by client */
  57.     byte     bp_sname[64];    /* optional server host name, null terminated*/
  58.  
  59.     byte     bp_file[128];    /* boot file name, null terminated string
  60.                    'generic' name or null in bootrequest,
  61.                    fully qualified directory-path
  62.                    name in bootreply. */
  63.     byte     bp_vend[ 64];    /* optional vendor-specific area */
  64. };
  65.  
  66.  
  67. extern struct bootp _bootp;
  68.  
  69. /*
  70.  * UDP port numbers, server and client.
  71.  */
  72. #define    IPPORT_BOOTPS    67
  73. #define    IPPORT_BOOTPC    68
  74.  
  75.  
  76. /******** the following is stolen from NCSA which came from CUTCP *********/
  77. /* I have not implemented these, but someone may wish to in the future so */
  78. /* I kept them around.                                                    */
  79. /**************************************************************************/
  80.  
  81. /*
  82.  * "vendor" data permitted for Stanford boot clients.
  83.  */
  84. struct vend {
  85.     byte      v_magic[4];    /* magic number */
  86.     longword v_flags;    /* flags/opcodes, etc. */
  87.     byte      v_unused[56];    /* currently unused */
  88. };
  89.  
  90. #define    VM_STANFORD    "STAN"    /* v_magic for Stanford */
  91. #define VM_RFC1048      "\x63\x82\x53\x63" /* magic cookie for BOOTP */
  92.                     /* high byte listed first */
  93.  
  94. /* v_flags values */
  95. #define    VF_PCBOOT    1    /* an IBMPC or Mac wants environment info */
  96. #define    VF_HELP        2        /* help me, I'm not registered */
  97. #define TAG_BOOTFILE_SIZE       13     /* tag used by vend fields rfc 1048 */
  98.  
  99. /* global variables */
  100. longword bootphost = 0xffffffffL;    /* broadcast */
  101. word bootptimeout = 30;
  102. word bootpon = 0;
  103.  
  104. extern longword set_timeout();
  105.  
  106.  
  107. /*
  108.  * dobootpc - Checks global variables bootptimeout, bootphost
  109.  *             if no host specified, the broadcast address
  110.  *             returns 0 on success and sets ip address
  111.  */
  112. int dobootp()
  113. {
  114.     udp_Socket bsock;
  115.     longword sendtimeout, bootptmo;
  116.     word magictimeout;
  117.     word len, templen;
  118.     struct bootp sendbootp;            /* outgoing data */
  119.     struct bootp bootp;                /* incoming data */
  120.     struct bootp register * sbp, * rbp;
  121.     int status;
  122.     longword xid;
  123.     byte *p, *t;
  124.     int dummy;
  125.  
  126.     if (pktdevclass == PD_SLIP) return (-1);
  127.  
  128.     sbp = &sendbootp;            /* registered addresses */
  129.     rbp = &bootp;
  130.     memset((byte *)sbp, 0, sizeof(struct bootp));
  131.     memset((byte *)rbp, 0, sizeof(struct bootp));
  132.  
  133.     outs("\r\n Requesting a Bootp server ");
  134.     /* We must get Waterloo TCP to use IP address 0 for sending */
  135.     xid = my_ip_addr;   /* a unique value coming from the ethernet card */
  136.     my_ip_addr = 0;
  137.  
  138.     if (udp_open(&bsock, IPPORT_BOOTPC, bootphost, IPPORT_BOOTPS, NULL) == 0)
  139.     {
  140.         outs("\n\r Unable to find a bootp server");
  141.         return (-1);
  142.     }
  143.  
  144.     bootptmo = set_timeout(bootptimeout);
  145.     magictimeout = (xid & 7) + 7;          /* between 7 and 14 seconds */
  146.  
  147.     sbp->bp_op = BOOTREQUEST;
  148.     sbp->bp_htype = pktdevclass;
  149.             /* Copy into position the Magic Number used by Bootp */
  150.     bcopy(VM_RFC1048, sbp->bp_vend, 4);        /* high byte first */
  151.  
  152.     if (pktdevclass == PD_ETHER) sbp->bp_hlen = 6;
  153.  
  154.     sbp->bp_xid = xid;
  155.     sbp->bp_secs = intel16(1);
  156.  
  157.     bcopy(eth_addr, sbp->bp_chaddr, sizeof(eth_address));
  158.  
  159.     while (1) {
  160.     sock_fastwrite(&bsock, (byte *)sbp, sizeof(struct bootp));
  161.         sbp->bp_secs += magictimeout;            /* for next time */
  162.         sendtimeout = set_timeout(magictimeout += (xid > 5) & 7);
  163.     outs(".");                /* progress tics */
  164.         while (chk_timeout(sendtimeout) == 0) {
  165.             if (chk_timeout(bootptmo))
  166.                 {
  167.             outs(" Timed out, sorry");
  168.                     goto give_up;
  169.             }
  170.             sock_tick(&bsock, &status);
  171.             if (len = sock_dataready(&bsock)) {
  172.  
  173.                 /* got a response, lets consider it */
  174.                 templen = sock_fastread(&bsock, (byte *)rbp, 
  175.             sizeof(struct bootp));
  176.                 if (templen < sizeof(struct bootp)) {
  177.                     /* too small, not a bootp packet */
  178.             bcopy((byte *)rbp, 0, sizeof(struct bootp));
  179.                     continue;
  180.                 }
  181.  
  182.                 /* we must see if this is for us */
  183.         if (rbp->bp_xid != sbp->bp_xid) {
  184.             bcopy((byte *)rbp, 0, sizeof(struct bootp));
  185.                     continue;
  186.                 }
  187.  
  188.                 /* we must have found it */
  189.         my_ip_addr = intel(rbp->bp_yiaddr);
  190.  
  191.         if (*(long *)rbp->bp_vend == *(long *)sbp->bp_vend)
  192.             {            /* if magic cookies match */
  193.             /*RFC1048 complient BOOTP vendor field */
  194.             /* Based heavily on NCSA Telnet BOOTP */
  195.             p = &rbp->bp_vend[4]; /* Point just after vendor field */
  196.  
  197.             while (*p != 255) {
  198.             switch(*p) {
  199.                           case 0: /* Nop Pad character */
  200.                                  p++;
  201.                                  break;
  202.                           case 1: /* Subnet Mask */
  203.                  sin_mask = intel(*(longword *)(&p[2]));
  204.                  /* and fall through */
  205.               case 2: /* Time offset */
  206.                  p += *(p+1) + 2;
  207.                  break;
  208.               case 3: /* gateways */
  209.                 for (len = 0; len < *(p+1); len += 4)
  210.                   arp_add_gateway(NULL,
  211.                      intel(*(longword*)(&p[2 + len])));
  212.                           /* and fall through */
  213.               case 4: /*time servers */
  214.                           /* fall through */
  215.                           case 5: /* IEN=116 name server */
  216.                                  p +=*(p+1)+2;
  217.                                  break;
  218.               case 6: /* Domain Name Servers (BIND) */
  219.                 for (len = 0; len < *(p+1); len += 4)
  220.                     add_server(&last_nameserver,
  221.                     MAX_NAMESERVERS, def_nameservers,
  222.                         intel(*(longword*)(&p[2 + len])));
  223.                         /* and fall through */
  224.               case 7: /* log server */
  225.                  p += *(p+1)+2;
  226.                  break;
  227.               case 8: /* cookie server */
  228.                  for (len = 0; len < *(p+1); len += 4)
  229. #ifdef KERMIT
  230.     ;    /* omit cookie server with Kermit */
  231. #else
  232.                      add_server(&last_cookie, MAX_COOKIES,
  233.                     cookie, intel(*(longword*)(&p[2+len])));
  234. #endif /* KERMIT */
  235.                  /* and fall through */
  236.                           case 9: /* lpr server */
  237.                           case 10: /* impress server */
  238.                           case 11: /* rlp server */
  239.                    p +=*(p+1)+2;
  240.                                    break;
  241.               case 12: /* Client Hostname */
  242.                   bcopy(&p[2], hostname, MAX_STRING);
  243.                   hostname[MAX_STRING - 1] = 0;
  244.                   p += *(p+1)+2;
  245.                                   break;
  246.                           case 255:
  247.                                    break;
  248.                           default:
  249.                                    p +=*(p+1)+2;
  250.                                    break;
  251.                         } /* end of switch */
  252.                      } /* end of while */
  253.                 }/* end of RFC_1048 if */
  254.                 goto give_up;
  255.             }
  256.         }
  257.     }
  258. give_up:
  259.     sock_close(&bsock);
  260.     if (my_ip_addr != 0) outs(" succeeded.\r\n");
  261.     return (my_ip_addr == 0);  /* return 0 on success */
  262.  
  263. sock_err:
  264.     /* major network error if UDP fails */
  265.     sock_close(&bsock);
  266.     return (-1);
  267. }
  268.